//
//  MsgLogic.m
//  MyApplication
//
//  Created by issac on 15/7/29.
//  Copyright (c) 2015年 52xiaoluo. All rights reserved.
//

#import "MsgLogic.h"
#import "SecrityLogic.h"
#import "FuseMsg.h"
#import "message.pb.h"
#import "DataBaseSimple.h"
#import "QueueLogic.h"
#import "ViewRoomLogic.h"

#define MSGSEQ @"msgSeq"
@interface MsgLogic()
{
    NSMutableArray* m_array;
    UInt64 msgSeq;
    
    BOOL isPulling;//正在拉取消息
    DataBaseSimple *db;
    NSUserDefaults *profile;
}
@end

@implementation MsgLogic

static MsgLogic* _instance = nil;
+(instancetype) shareInstance
{
    static dispatch_once_t onceToken ;
    dispatch_once(&onceToken, ^{
        _instance = [[MsgLogic alloc] init] ;
    });
    
    return _instance ;
}

-(id)init {
    self = [super init];
    if (self) {
         m_array = [[NSMutableArray alloc] init];
        [[UserModuleManager shareInstance] registerUserModule:self];
    }

    return self;
}

#pragma mark - UserModule

-(void)userLogin {
    DLog(@"userLogin");
    [NetEngine shareInstance].pushDelegate = self;
    isPulling = NO;
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(netWorkChange:)
                                                 name:NetConnectNotifi
                                               object:nil];
    db = [[DataBaseSimple alloc] initWithDB:[[UserLogic shareInstance] getDBName]];
    profile = [[UserLogic shareInstance] getUserDefault];
    [self loadDataBase];
    [self loadMsgSeq];
    [self pullMsg];
    
}

-(void)userLogout {
    DLog(@"userLogout");
    [NetEngine shareInstance].pushDelegate = nil;
    isPulling = NO;
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [m_array removeAllObjects];
    if (db) {
        [db close];
        db = nil;
    }
}

- (NSArray *)getMsg_Array
{
    if (m_array) {
        
        return m_array;
    }
    else
    {
        return nil;
        
    }
}

- (void)loadDataBase
{
    dispatch_async([[QueueLogic shareInstance]getWorkQueue], ^{
        
        NSArray *msgArray = [db selectAll];
        if (msgArray.count!= 0) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [m_array setArray:msgArray];
            });
        }
    });
}

-(void) loadMsgSeq {
    NSNumber *num  = [profile objectForKey:MSGSEQ];
    if (num == nil) {
        msgSeq = 0;
    } else {
        msgSeq = [num longValue];
    }
    DLog(@"loadMsgSeq ,cliseq %lld",msgSeq);
}

- (void)saveMsgSeq:(UInt64)seq
{
    msgSeq = seq;
    DLog(@"saveMsgSeq ,seq %lld",msgSeq);
    if (seq > 0) {
        [profile setObject:[NSNumber numberWithLong:seq] forKey:MSGSEQ];
    } else {
        [profile removeObjectForKey:MSGSEQ];
    }
}



-(void) pullMsg {
    if (isPulling) {
        DLog(@"pullMsg isPulling return");
        return;
    }
    if ([[UserLogic shareInstance] getUserId] <= 0) {
        DLog(@"pullMsg no login return");
        return;
    }
    GetMsgReqBuilder *gmrB = [[GetMsgReqBuilder alloc] init];
    [gmrB setCliSeq:msgSeq];
    [gmrB setSyncFlag:MsgSyncFlagSyncBegin];
    [self sendRequest:CMD_MSG_PULL PBMsg:gmrB.build];
    isPulling = YES;
}



-(void) onPush:(Packet *)packet {
    NSData *plain = [[SecrityLogic shareInstance] decryptSession:packet.eBody];
    MsgPush *msgPush = [MsgPush parseFromData:plain];
    DLog(@"onPush pushSeq,%lld,cliSeq %lld",msgPush.svrSeq,msgSeq);
    if (msgPush.svrSeq > msgSeq) {
        [self pullMsg];
    }
}

-(void) onPushPlain:(Packet *)packet {
    if (packet == nil) {
        return;
    }
    MsgPush *msgPush = [MsgPush parseFromData:packet.eBody];
    DLog(@"onPushPlain pushSeq,%lld,cliSeq %lld",msgPush.svrSeq,msgSeq);
    if (msgPush.svrSeq > msgSeq) {
        [self pullMsg];
    }
}

-(void) onConnConnect {
    DLog(@"onConnConnect");
    [self pullMsg];
}

-(void) onConnDisconnect {

}

#pragma mark - NetConnectNotifi
-(void) netWorkChange:(NSNotification *)noti
{
    NSDictionary *dic = noti.object;
    NSString *statusOld = dic[@"old"];
    NSString *statusNew = dic[@"new"];

    if ([statusOld integerValue] == 0) {
        [self pullMsg];
    }
    if ([statusNew integerValue] == 0)
    {
        isPulling = NO;
    }
    
}

#pragma mark - RequestDelegate
- (void)onResult:(Packet *)result req:(Request *)req
{
    NSData *plain =[[SecrityLogic shareInstance] decryptSession:result.eBody];
    if([result.cmd isEqualToString:CMD_MSG_PULL]) {
        isPulling = NO;
        if (result.ret == 0) {
            GetMsgResp *getMsgResp = [GetMsgResp parseFromData:plain];
            if (getMsgResp != nil) {
                DLog(@"recv msg start ,cliseq %lld,svrSeq %lld,%ld",msgSeq,getMsgResp.srvSeq,getMsgResp.msg.count);
                
                NSMutableArray *newFuseArray = [[NSMutableArray alloc]init];
                
                NSMutableArray *orderArray = [[NSMutableArray alloc]init];
                for (int i = (int)getMsgResp.msg.count - 1; i >= 0; i--) {
                    Msg * msg = getMsgResp.msg[i];
                    if (i<=(int)getMsgResp.msg.count - 2) {
                        Msg *pre = getMsgResp.msg[i + 1];
                        if (msg.msgHead.msgSeq == pre.msgHead.msgSeq) {
                            continue;
                        }
                    }
                    if (msg.msgHead.msgSeq > msgSeq) {
                        FuseMsg *fuseMsg = [[FuseMsg alloc] init];
                        fuseMsg.msg = msg;
                        fuseMsg.recieveTimeStamp = [KMGetDate nowTimeSp];
                        [m_array insertObject:fuseMsg atIndex:0];
                        [newFuseArray addObject:fuseMsg];
                        if (msg.msgHead.msgType == MsgTypeNewViewOrder) {
                            [orderArray addObject:msg];
                        }
                    }
                }
                [db insertDBwithFuseMsgArray:newFuseArray useTransaction:YES];
                [[NSNotificationCenter defaultCenter]postNotificationName:@"messageNotifi" object:m_array];
                [self saveMsgSeq:getMsgResp.srvSeq];
                [[ViewRoomLogic shareInstance] recieveOrderPush:orderArray];
            }
            GetMsgAckBuilder *getMsgAck = [[GetMsgAckBuilder alloc] init];
            [getMsgAck setCliSeq:msgSeq];
            [self sendRequest:CMD_MSG_PULLACK PBMsg:getMsgAck.build];
        } else {
            DLog(@"pullMsgError");
        }
    } else if ([result.cmd isEqualToString:CMD_MSG_PULLACK]){
        DLog(@"pull ack");
    }
}


@end
